import * as Cesium from '@cesiumjs';
import {
  G3xObjBase
} from "@g3xObj"
import * as gexUtils from "@g3x/utils";
import {
  autorun,
  reaction,
  intercept,
  extendObservable,
  computed
} from 'mobx';

/**
 * 折线材质
 * @namespace
 * @name Material
 * @memberof Obj.Polyline
 */

/**
 * 纯色材质
 * @class
 * @memberof Obj.Polyline.Material
 * @extends XbsjBase
 */
class Color extends G3xObjBase {

  constructor(options) {
    super(options);
    const _this = this;
    extendObservable(_this, {
      _material: Cesium.Material.fromType('Color'),
      get material() {
        return this._material;
      }
    }, {
      material: computed
    });

    _this.disposers.push(autorun(() => {
      Cesium.Color.apply(_this._material.uniforms.color, _this.color)
    }));
  }
}

Color.defaultOptions = {
  /**
   * 颜色叠加
   * @type {array}
   * @instance
   * @default [1, 1, 1, 1]
   * @memberof Obj.Polyline.Material.Color
   */
  color: [1, 1, 1, 1]
  // color: { type: 'array', items: { type: 'number' }, minItems: 4, maxItems: 4, default: [1, 1, 1, 1], description: '颜色叠加'},
};

/**
 * 点画线材质
 * @class
 * @memberof Obj.Polyline.Material
 * @extends XbsjBase
 */
class PolylineDash extends G3xObjBase {

  constructor(options) {

    super(options);
    const _this = this;
    extendObservable(_this, {
      _material: Cesium.Material.fromType('PolylineDash'),
      get material() {
        return this._material;
      }
    }, {
      material: computed
    });

    _this.disposers.push(autorun(()=>{
      Object.keys(_this.defaultOptions).forEach(function(key) {
        const val = _this[key];
        const uniforms = _this._material.uniforms;
        if (key === 'color' || key === 'gapColor') {
          uniforms[key] = new(Function.prototype.bind.apply(Cesium.Color, [null, ...val]))();
        } else {
          uniforms[key] = val;
        }
      });
    }));
  }
}

PolylineDash.defaultOptions = {
  /**
   * 颜色叠加 color for the line.
   * @type {array}
   * @instance
   * @default [1, 0, 1, 1]
   * @memberof Obj.Polyline.Material.PolylineDash
   */
  color: [1, 0, 1, 1], // color for the line.
  /**
   * 间隙颜色叠加 color for the gaps in the line.
   * @type {array}
   * @instance
   * @default [0, 0, 0, 0]]
   * @memberof Obj.Polyline.Material.PolylineDash
   */
  gapColor: [0, 0, 0, 0], // color for the gaps in the line.
  /**
   * Dash length in pixels.
   * @type {number}
   * @instance
   * @default 16
   * @memberof Obj.Polyline.Material.PolylineDash
   */
  dashLength: 16, // Dash length in pixels.
  /**
   * The 16 bit stipple pattern for the line..
   * @type {number}
   * @instance
   * @default 255
   * @memberof Obj.Polyline.Material.PolylineDash
   */
  dashPattern: 255 // The 16 bit stipple pattern for the line..
};

/**
 * 箭头材质
 * @class
 * @memberof Obj.Polyline.Material
 * @extends XbsjBase
 */
class PolylineArrow extends G3xObjBase {

  constructor(options) {

    super(options);
    const _this = this;
    extendObservable(_this, {
      _material: Cesium.Material.fromType('PolylineArrow'),
      get material() {
        return this._material;
      }
    }, {
      material: computed
    });

    _this.disposers.push(autorun(function() {
      Object.keys(_this.defaultOptions).forEach(function(key) {
        const val = _this[key];
        const uniforms = _this._material.uniforms;
        if (key === 'color') {
          uniforms[key] = new(Function.prototype.bind.apply(Cesium.Color, [null, ...val]))();
        } else {
          uniforms[key] = val;
        }
      });
    }));
  }
}

PolylineArrow.defaultOptions = {
  /**
   * 颜色叠加
   * @type {array}
   * @instance
   * @default [1, 1, 1, 1]
   * @memberof Obj.Polyline.Material.PolylineArrow
   */
  color: [1, 1, 1, 1]
};

/**
 * 发光材质
 * @class
 * @memberof Obj.Polyline.Material
 * @extends XbsjBase
 */
class PolylineGlow extends G3xObjBase {
  constructor(options) {
    super(options);
    const _this = this;
    extendObservable(_this, {
      _material: Cesium.Material.fromType('PolylineGlow'),
      get material() {
        return this._material;
      }
    }, {
      material: computed
    });

    _this.disposers.push(autorun(function() {
      Object.keys(_this.defaultOptions).forEach(function(key) {
        const val = _this[key];
        const uniforms = _this._material.uniforms;
        if (key === 'color') {
          uniforms[key] = new(Function.prototype.bind.apply(Cesium.Color, [null, ...val]))
        ();
        } else {
          uniforms[key] = val;
        }
      });
    }));
  }
}

PolylineGlow.defaultOptions = {
  /**
   * 颜色叠加
   * @type {array}
   * @instance
   * @default [1, 1, 1, 1]
   * @memberof Obj.Polyline.Material.PolylineGlow
   */
  color: [1, 1, 1, 1], // color and maximum alpha for the glow on the line.
  /**
   * strength of the glow, as a percentage of the total line width (less than 1.0).
   * @type {number}
   * @instance
   * @default 0.25
   * @memberof Obj.Polyline.Material.PolylineGlow
   */
  glowPower: 0.25, // strength of the glow, as a percentage of the total line width (less than 1.0).
  /**
   * strength of the tapering effect, as a percentage of the total line length. If 1.0 or higher, no taper effect is used.
   * @type {number}
   * @instance
   * @default 1.0
   * @memberof Obj.Polyline.Material.PolylineGlow
   */
  taperPower: 1.0 // strength of the tapering effect, as a percentage of the total line length. If 1.0 or higher, no taper effect is used.
};

/**
 * 发光材质
 * @class
 * @memberof Obj.Polyline.Material
 * @extends XbsjBase
 */
class PolylineColorGlow extends G3xObjBase {
  constructor(options) {
    super(options);
    const _this = this;
    extendObservable(_this, {
      _material: Cesium.Material.fromType('PolylineColorGlow'),
      get material() {
        return this._material;
      }
    }, {
      material: computed
    });

    _this.disposers.push(autorun(function() {
      Object.keys(_this.defaultOptions).forEach(function(key) {
        const uniforms = _this._material.uniforms;
        const val = _this[key];
        if (key === 'color' || key === 'glowColor') {
          uniforms[key] = new (Function.prototype.bind.apply(Cesium.Color, [null, ...val]))();
        } else {
          uniforms[key] = val;
        }
      });
    }));
  }
}

PolylineColorGlow.defaultOptions = {
  /**
   * 颜色叠加
   * @type {array}
   * @instance
   * @default [1, 1, 1, 1]
   * @memberof Obj.Polyline.Material.PolylineGlow
   */
  color: [1, 1, 1, 1], // color and maximum alpha for the glow on the line.
  glowColor: [1, 0, 0, 0.5],
  /**
   * strength of the glow, as a percentage of the total line width (less than 1.0).
   * @type {number}
   * @instance
   * @default 0.25
   * @memberof Obj.Polyline.Material.PolylineGlow
   */
  glowPower: 0.25, // strength of the glow, as a percentage of the total line width (less than 1.0).
  /**
   * strength of the tapering effect, as a percentage of the total line length. If 1.0 or higher, no taper effect is used.
   * @type {number}
   * @instance
   * @default 1.0
   * @memberof Obj.Polyline.Material.PolylineGlow
   */
  taperPower: 1.0 // strength of the tapering effect, as a percentage of the total line length. If 1.0 or higher, no taper effect is used.
};

/**
 * 外轮廓材质
 * @class
 * @memberof Obj.Polyline.Material
 * @extends XbsjBase
 */
class PolylineOutline extends G3xObjBase {
  constructor(options) {
    super(options);
    const _this = this;
    extendObservable(_this, {
      _material: Cesium.Material.fromType('PolylineOutline'),
      get material() {
        return this._material;
      }
    }, {
      material: computed
    });

    _this.disposers.push(autorun(function() {
      Object.keys(_this.defaultOptions).forEach(function(key) {
        const val = _this[key];
        if (key === 'color' || key === 'outlineColor') {
          _this._material.uniforms[key] = new(Function.prototype.bind.apply(Cesium.Color, [null, ...val]))
        ();
        } else {
          _this._material.uniforms[key] = val;
        }
      });
    }));
  }
}
PolylineOutline.defaultOptions = {
  /**
   * 颜色叠加
   * @type {array}
   * @instance
   * @default [1, 1, 1, 1]
   * @memberof Obj.Polyline.Material.PolylineOutline
   */
  color: [1, 1, 1, 1],
  /**
   * 外轮廓颜色叠加
   * @type {array}
   * @instance
   * @default [1, 1, 1, 1]
   * @memberof Obj.Polyline.Material.PolylineOutline
   */
  outlineColor: [1, 1, 1, 1],
  /**
   * 外轮廓宽度
   * @type {number}
   * @instance
   * @default 0.25
   * @memberof Obj.Polyline.Material.PolylineOutline
   */
  outlineWidth: 0.25
};

/**
 * OD线材质
 * @class
 * @memberof Obj.Polyline.Material
 * @extends XbsjBase
 */
class ODLine extends G3xObjBase {
  constructor(options) {
    super(options);
    const _this = this;
    extendObservable(_this, {
      _material: Cesium.Material.fromType('ODLine'),
      get material() {
        return this._material;
      }
    }, {
      material: computed
    });

    _this.disposers.push(autorun(function() {
      Object.keys(_this._defaultOptions).forEach(function(key) {
        const val = _this[key];
        if (key === 'color') {
          _this._material.uniforms[key] = new(Function.prototype.bind.apply(Cesium.Color, [null, ...val]))
        ();
        } else {
          _this._material.uniforms[key] = val;
        }
      });
    }));
  }
}

ODLine.defaultOptions = {
  /**
   * 颜色叠加
   * @type {array}
   * @instance
   * @default [1, 1, 0, 1]
   * @memberof Obj.Polyline.Material.XbsjODLine
   */
  color: [1, 1, 0, 1],
  /**
   * 一次动画的循环帧数
   * @type {number}
   * @instance
   * @default 45
   * @memberof Obj.Polyline.Material.XbsjODLine
   */
  totoalFrameCount: 45
};

export function create(type, option) {
  if (type === "ColorMaterial") {
    return new Color(option)
  }
  if (type === "PolylineDashMaterial") {
    return new PolylineDash(option)
  }
  if (type === "PolylineGlowMaterial") {
    return new PolylineGlow(option)
  }
  if (type === "PolylineOutlineMaterial") {
    return new PolylineOutline(option)
  }
  if (type === "ODLineMaterial") {
    return new ODLine(option)
  }
}

export function getMaterial(material,type){
  let m = material[type].material;
  if(!m){
    material[type].material = (m = createMaterials(type))
  }
  return m;
}

export default getMaterial;

export {
  Color,
  PolylineDash,
  PolylineGlow,
  PolylineColorGlow,
  PolylineOutline,
  ODLine
}
